# -*- coding: utf-8 -*- #

"""
同步的数据库操作公用方法
"""

from pymongo import MongoClient

import MySQLdb
from MySQLdb.cursors import DictCursor
from DBUtils.PooledDB import PooledDB


class SyncMySqlDbUtils(object):
    """
        MYSQL数据库对象，负责产生数据库连接 , 此类中的连接采用连接池实现
        获取连接对象：conn = Mysql.getConn()
        释放连接对象;conn.close()或del conn
    """
    #连接池对象
    __pool = None

    def __init__(self, db_conn_dict):
        """
        数据库构造函数，从连接池中取出连接，并生成操作游标
        """

        self._conn = SyncMySqlDbUtils.__getConn(db_conn_dict)
        self._cursor = self._conn.cursor()


    def reinit(self):

        self._conn = SyncMySqlDbUtils.__getConn()
        self._cursor = self._conn.cursor()


    @staticmethod
    def __getConn(db_conn_dict):
        """
        @summary: 静态方法，从连接池中取出连接
        @return MySQLdb.connection
        """
        if SyncMySqlDbUtils.__pool is None:

            '''
            mincached : 启动时开启的闲置连接数量(缺省值 0 以为着开始时不创建连接)
            maxcached : 连接池中允许的闲置的最多连接数量(缺省值 0 代表不闲置连接池大小)
            maxshared : 共享连接数允许的最大数量(缺省值 0 代表所有连接都是专用的)如果达到了最大数量,被请求为共享的连接将会被共享使用
            maxconnecyions : 创建连接池的最大数量(缺省值 0 代表不限制)
            blocking : 设置在连接池达到最大数量时的行为(缺省值 0 或 False 代表返回一个错误<toMany......>; 其他代表阻塞直到连接数减少,连接被分配)
            maxusage : 单个连接的最大允许复用次数(缺省值 0 或 False 代表不限制的复用).当达到最大数时,连接会自动重新连接(关闭和重新打开)
            setsession : 一个可选的SQL命令列表用于准备每个会话，如["set datestyle to german", ...]
            '''

            # Mysql.__pool = PooledDB(creator=MySQLdb, mincached=1 , maxcached=20 ,
            #                   host=MYSQL_DBHOST , port=MYSQL_DBPORT , user=MYSQL_DBUSER , passwd=MYSQL_DBPWD,
            #                   db=MYSQL_DBNAME,use_unicode=False,charset=MYSQL_DBCHAR,cursorclass=DictCursor)

            SyncMySqlDbUtils.__pool = PooledDB(creator=MySQLdb,
                                               mincached=db_conn_dict['mincached'],
                                               maxcached=db_conn_dict['maxcached'],
                                               host=db_conn_dict['host'],
                                               port=db_conn_dict['port'],
                                               user=db_conn_dict['user'],
                                               passwd=db_conn_dict['pwd'],
                                               db=db_conn_dict['db'],
                                               use_unicode=False,
                                               charset=db_conn_dict['charset'],
                                               cursorclass=DictCursor)
        #     print 'new pool'
        # else:
        #     print 'global pool'

        return SyncMySqlDbUtils.__pool.connection()


    def get_all(self, sql, param=None):
        """
        @summary: 执行查询，并取出所有结果集
        @param sql:查询ＳＱＬ，如果有查询条件，请只指定条件列表，并将条件值使用参数[param]传递进来
        @param param: 可选参数，条件列表值（元组/列表）
        @return: result list/boolean 查询到的结果集
        """
        if param is None:
            count = self._cursor.execute(sql)
        else:
            count = self._cursor.execute(sql,param)
        if count>0:
            result = self._cursor.fetchall()
        else:
            result = False
        return result


    def get_one(self, sql, param=None):
        """
        @summary: 执行查询，并取出第一条
        @param sql:查询ＳＱＬ，如果有查询条件，请只指定条件列表，并将条件值使用参数[param]传递进来
        @param param: 可选参数，条件列表值（元组/列表）
        @return: result list/boolean 查询到的结果集
        """
        if param is None:
            count = self._cursor.execute(sql)
        else:
            count = self._cursor.execute(sql,param)
        if count>0:
            result = self._cursor.fetchone()
        else:
            result = False
        return result


    def get_many(self, sql, num, param=None):
        """
        @summary: 执行查询，并取出num条结果
        @param sql:查询ＳＱＬ，如果有查询条件，请只指定条件列表，并将条件值使用参数[param]传递进来
        @param num:取得的结果条数
        @param param: 可选参数，条件列表值（元组/列表）
        @return: result list/boolean 查询到的结果集
        """
        if param is None:
            count = self._cursor.execute(sql)
        else:
            count = self._cursor.execute(sql,param)
        if count>0:
            result = self._cursor.fetchmany(num)
        else:
            result = False
        return result


    def insert_one(self, sql, param=None):
        """
        @summary: 向数据表插入一条记录
        @param sql:要插入的ＳＱＬ格式
        @param value:要插入的记录数据tuple/list
        @return: insertId 受影响的行数
        """
        if param:
            self._cursor.execute(sql,param)
        else:
            self._cursor.execute(sql)
        return self.__get_insert_id()


    def insert_many(self, sql, values):
        """
        @summary: 向数据表插入多条记录
        @param sql:要插入的ＳＱＬ格式
        @param values:要插入的记录数据tuple(tuple)/list[list]
        @return: count 受影响的行数
        """
        count = self._cursor.executemany(sql,values)
        return count


    def __get_insert_id(self):
        """
        获取当前连接最后一次插入操作生成的id,如果没有则为０
        """
        self._cursor.execute("SELECT @@IDENTITY AS id")
        result = self._cursor.fetchall()
        return result[0]['id']


    def __query(self, sql, param=None):
        if param is None:
            count = self._cursor.execute(sql)
        else:
            count = self._cursor.execute(sql,param)
        return count


    def update(self, sql, param=None):
        """
        @summary: 更新数据表记录
        @param sql: ＳＱＬ格式及条件，使用(%s,%s)
        @param param: 要更新的  值 tuple/list
        @return: count 受影响的行数
        """
        return self.__query(sql,param)


    def delete(self, sql, param=None):
        """
        @summary: 删除数据表记录
        @param sql: ＳＱＬ格式及条件，使用(%s,%s)
        @param param: 要删除的条件 值 tuple/list
        @return: count 受影响的行数
        """
        return self.__query(sql,param)


    def begin(self):
        """
        @summary: 开启事务
        """
        #self._conn.autocommit(0)
        self._conn.autocommit(True)
        #dbmysql.autocommit(True)


    def end(self, option='commit'):
        """
        @summary: 结束事务
        """
        if option=='commit':
            self._conn.commit()
        else:
            self._conn.rollback()


    def dispose(self, isEnd=1):
        """
        @summary: 释放连接池资源
        """
        if isEnd==1:
            self.end('commit')
        else:
            self.end('rollback');
        self._cursor.close()
        self._conn.close()


class SyncMongodbUtils(object):
    """
    mongodb操作类
    """

    def __init__(self, db_conn_dict):
        """
        数据库连接
        :param db_conn_dict:数据库连接参数
        :return:
        """
        self.client = SyncMongodbUtils.create_pool(db_conn_dict)

    def get_collection(self, db_name, collection_name):
        """
         获取指定数据库中的collection
        :param db_name:
        :param collection_name:
        :return:
        """
        db = self.client[db_name]
        return db[collection_name]

    @staticmethod
    def create_pool(para):
        """
        生成数据库连接池
        :param para: 数据库配置参数
        :param cursor_class:
        :return:
        """
        client = MongoClient(para['mongo_auth_url'])
        return client